#include "stdafx.h"
#include "RenderViewport.h"

QPreviewDockWidget::QPreviewDockWidget(QWidget* parent) 
	: QWidget( parent )
	, mEntity( NULL )
	, mSpeed( 0 )
	, mSettings( NULL )
{
	mLayout = new QVBoxLayout( this );
	setLayout( mLayout );

	mZoom		= new QZoomWidget(this);
    mOgreWidget = new OgreWidget(this);
	mFitEntity	= new QPushButton( "fit", this );
	mRotateSpeed = new QSlider( Qt::Horizontal, this );

	mLayout->addWidget( mOgreWidget );
	mLayout->addWidget( mRotateSpeed );
	
	mRotateSpeed->setRange( -100, 100 );
	mRotateSpeed->setSliderPosition(0);

	QHBoxLayout * layRotator = new QHBoxLayout(this);
	layRotator->addWidget( new QLabel("Speed", this) );
	layRotator->addWidget( mRotateSpeed );
	mRotationLabel = new QLabel( "0", this );
	layRotator->addWidget( mRotationLabel );
	mLayout->addLayout( layRotator );
	
	connect( mRotateSpeed, SIGNAL(valueChanged(int)), this, SLOT(rotateSpeedChanged(int)) );

	QWidget* zoomW = new QWidget( this );
	zoomW->setLayout( new QHBoxLayout(this) );
	zoomW->layout()->addWidget( mZoom );
	zoomW->layout()->addWidget( mFitEntity );
		
	//mLayout->addItem( new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding) );
	mLayout->addWidget( zoomW, 0, Qt::AlignBottom );
		
	mOgreWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
	zoomW->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
	setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );

	mOgreWidget->setMinimumSize( 128, 128 );
		
	connect( mZoom, SIGNAL(valueChanged(int)), this, SLOT(zoomValueChanged(int)) );
	connect( mFitEntity, SIGNAL(clicked(bool)), this, SLOT(fitEntityClicked(bool)) );
}
QPreviewDockWidget::~QPreviewDockWidget( )
{
	if( mRotationLabel ) delete mRotationLabel, mRotationLabel = NULL;
	if( mRotateSpeed ) delete mRotateSpeed, mRotateSpeed = NULL;
	if( mSettings ) delete mSettings, mSettings = NULL;
	mOgreWidget->ogreRoot()->removeFrameListener(this);
	if( mEntity ) delete mEntity, mEntity = NULL;
	if( mOgreWidget ) delete mOgreWidget, mOgreWidget = NULL;
	if( mZoom ) delete mZoom, mZoom = NULL;
	if( mLayout ) delete mLayout, mLayout = NULL;
}

void QPreviewDockWidget::rotateSpeedChanged( int v )
{
	mSpeed = v;
	if( mRotationLabel ) mRotationLabel->setText( QString::number(v) );
}
void QPreviewDockWidget::showSettings( Lit::ResourcesList * res ){
	mSettings->exec( res );
}
Lit::DisplayEntity* QPreviewDockWidget::entity() const{ return mEntity; }
void QPreviewDockWidget::replaceMesh( const std::string &mesh )
{
	mEntity->replaceMesh( mesh );
	fitEntity();
}
void QPreviewDockWidget::showEvent( QShowEvent*evt )
{
	QWidget::showEvent(evt);
	//resize( sizeHint() );	
	if( !mEntity ){
		mEntity = new Lit::DisplayEntity( "PreviewEntity", "penguin.mesh", mOgreWidget->ogreSceneManager() );
		fitEntity();
		mOgreWidget->ogreRoot()->addFrameListener(this);
		
		mSettings = new PreviewSettings( this );
	}
}
void QPreviewDockWidget::fitEntity() 
{
	Ogre::AxisAlignedBox bbox = mEntity->boundingBox();

	Ogre::Vector3 offset = bbox.getMaximum() - bbox.getCenter(); // Radius of bounding sphere
	Ogre::Vector3 center = bbox.getCenter();

	mOgreWidget->ogreCamera()->setPosition( center );
	float oneOverSine = 1.0f / (float)Ogre::Math::Tan( mOgreWidget->ogreCamera()->getFOVy().valueRadians()/2.0 );
	float distanceToCenter = offset.length() * oneOverSine; // (adjacent / opposite) * opposite = adjacent
	mOgreWidget->ogreCamera()->move( Ogre::Vector3(1, 1, 1).normalisedCopy() * distanceToCenter);
	mOgreWidget->ogreCamera()->lookAt( center );
}

bool QPreviewDockWidget::frameRenderingQueued( const Ogre::FrameEvent& evt )
{
	if( mEntity )
		(*mEntity)->getParentSceneNode()->yaw(Ogre::Degree( mSpeed*evt.timeSinceLastFrame));
	return true;
}

OgreWidget* QPreviewDockWidget::ogreWidget() const{ return mOgreWidget; }

void QPreviewDockWidget::zoomValueChanged( int val )
{
	Ogre::Vector3 maxOut( val, 0, val );
	mOgreWidget->ogreCamera()->setPosition( maxOut );
	mOgreWidget->ogreCamera()->lookAt( Ogre::Vector3::ZERO );
	Ogre::LogManager::getSingleton().logMessage("Cam Pos: "+Ogre::StringConverter::toString(mOgreWidget->ogreCamera()->getPosition()));
}
void QPreviewDockWidget::fitEntityClicked( bool )
{
	fitEntity();
}

PreviewSettings::PreviewSettings(QPreviewDockWidget * preview) : SettingsDialog(preview), mPreview( preview ), mPage( NULL )
{
	mSceneNode = NULL;
	mPage = addPage( "General" );
}
PreviewSettings::~PreviewSettings(){}

void PreviewSettings::loadScene( std::string path )
{
	mCurrentScene = path;
	
	if( mSceneNode ) mPreview->ogreWidget()->ogreSceneManager()->destroySceneNode(mSceneNode);
	mSceneNode = mPreview->ogreWidget()->ogreSceneManager()->getRootSceneNode()->createChildSceneNode();
	Ogre::DotSceneLoader ldr;
	if( !ldr.parseDotScene( path, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mPreview->ogreWidget()->ogreSceneManager(), mSceneNode ) )
		throw Lit::RuntimeException(Lit::EXC_RUNTIME_ERROR, "Couldn't load scene '"+path+"' because \r\n"+ldr.lastError(), EXC_LOC);
}
int PreviewSettings::exec( Lit::ResourcesList * res )
{
	mPage->setProperty( "Ambient Light", mPreview->ogreWidget()->ogreSceneManager()->getAmbientLight() );
	Lit::StringList lst;
	int def=0;
	Ogre::MaterialManager::ResourceMapIterator itc=Ogre::MaterialManager::getSingleton().getResourceIterator();
	while( itc.hasMoreElements() ){
		Ogre::MaterialPtr m = itc.getNext();
		if( m->getGroup() == SKYBOX_RESOURCE_GROUP ){
			lst << m->getName();
			if( m->getName() == mCurrentSkybox ) lst.setDefault(def);
			def++;
		}
	}
	mPage->setProperty( "SkyBox", lst );
	
	def=1;
	lst = Lit::StringList();
	lst << "NONE";
	for( auto i=res->meshes().begin(); i!=res->meshes().end(); i++ )
	{
		lst << i->name().c_str();
		if( mPreview->entity()->mesh()->getName() == i->name() )
			lst.setDefault( def );
		def++;
	}

	mPage->setProperty( "Preview Mesh", lst );
	mPage->setFileProperty( "Preview Scene", mCurrentScene );
	mPage->updateUi();
	return 0;
}
